package com.mrdeer.iot.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mrdeer.common.entity.beans.PageEntity;
import com.mrdeer.common.exception.NotFoundException;
import com.mrdeer.iot.dto.DeviceEntityDTO;
import com.mrdeer.iot.entity.DeviceEntity;
import com.mrdeer.iot.service.DeviceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

@Slf4j
@Service
public class DeviceServiceImpl implements DeviceService {

    @Resource
    private MongoTemplate mongoTemplate;

    @Override
    public boolean deleteDeviceEntityById(String id) {
        Criteria criteria = new Criteria();
        if (null != id) {
            criteria.and("id").is(id);
        }
        Query query = new Query(criteria);
        DeviceEntity deviceEntity = mongoTemplate.findAndRemove(query, DeviceEntity.class);
        if (deviceEntity != null) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public DeviceEntity selectDeviceEntityById(String id) {
        Criteria criteria = new Criteria();
        if (null != id) {
            criteria.and("id").is(id);
        }
        Query query = new Query(criteria);
        DeviceEntity deviceEntity = mongoTemplate.findOne(query, DeviceEntity.class);
        return deviceEntity;
    }

    @Override
    public DeviceEntity selectDeviceEntityByName(String name) {
        Criteria criteria = new Criteria();
        if (null != name && name.length() > 0) {
            criteria.and("name").is(name);
        }
        Query query = new Query(criteria);
        DeviceEntity deviceEntity = mongoTemplate.findOne(query, DeviceEntity.class);
        return deviceEntity;
    }

    @Override
    public DeviceEntity update(DeviceEntity deviceEntity) {
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is(deviceEntity.getId()).and("address").is(deviceEntity.getAddress()));

        Update update = new Update();
        update.set("status", deviceEntity.getStatus());
        update.set("name", deviceEntity.getName());
        update.set("mac", deviceEntity.getMac());

        mongoTemplate.upsert(query, update, DeviceEntity.class, "deviceEntity");

        return deviceEntity;
    }

    @Override
    public DeviceEntity selectDeviceByAddress(String address) {
        Criteria criteria = new Criteria();
        if (null != address) {
            criteria.and("address").is(address);
        }
        Query query = new Query(criteria);
        try {
            DeviceEntity deviceEntity = mongoTemplate.findOne(query, DeviceEntity.class);
            return deviceEntity;
        } catch (NotFoundException e) {
            throw new NotFoundException("The Device does not exist");
        }
    }

    @Override
    public void addDevice(DeviceEntity deviceEntity) {
        if (null != deviceEntity) {
            mongoTemplate.insert(deviceEntity);
        }
    }

    @Override
    public void addDevices(List<DeviceEntity> entities) {
        if (null != entities) {
            if (entities.size() > 0) {
                mongoTemplate.insert(entities, DeviceEntity.class);
            }
        }
    }

    @Override
    public Page<DeviceEntity> deviceList(DeviceEntityDTO dto) {
        Criteria criteria = new Criteria();
        if (null == dto) {
            dto = new DeviceEntityDTO();
        }
        if (dto.getName() != null && (dto.getName().length() > 0)) {
            criteria.and("name").is(dto.getName());
        }
        if (null != dto.getAddress() && (dto.getAddress().length() > 0)) {
            criteria.and("address").is(dto.getAddress());
        }
        PageEntity page = null == dto.getPage() ? new PageEntity() : dto.getPage();
        Query query = new Query(criteria);
        long count = mongoTemplate.count(query, DeviceEntity.class);
        query.with(Sort.by(Sort.Direction.DESC, "originTime"));
        int size = (int) page.getSize();
        long current = page.getCurrent();
        query.limit(size).skip(size * (current - 1));
        List<DeviceEntity> deviceEntities = mongoTemplate.find(query, DeviceEntity.class);
        return (new Page<DeviceEntity>()).setCurrent(page.getCurrent()).setSize(page.getSize()).setTotal(count).setRecords(deviceEntities);
    }
}
